float4x4 World;
float4x4 View;
float4x4 Projection;

float3 CameraPosition;
float4x4 ReflectedView;

float3 BaseColor = float3(.2, .2, .8);
float BaseColorAmount = .3;

float WaveLength = 0.6;
float WaveHeight = 0.1;
float Time = 0;
float WaveSpeed = 0.04f;

texture ReflectionMap;
sampler2D reflectionSampler = sampler_state
{
    texture = <ReflectionMap>;
    MinFilter = Point;
    MagFilter = Point;
    AddressU = Mirror;
    AddressV = Mirror;
};
texture WaterNormalMap;
sampler2D waterNormalSampler = sampler_state
{
    texture = <WaterNormalMap>;
};

#include "Shared.fx"

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 UV : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float4 ReflectionPosition : TEXCOORD1;
    float2 NormalMapPosition : TEXCOORD2;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4x4 wvp = mul(World, mul(View, Projection));
    output.Position = mul(input.Position, wvp);

    float4x4 rwvp = mul(World, mul(ReflectedView, Projection));
    output.ReflectionPosition = mul(input.Position, rwvp);

    output.NormalMapPosition = input.UV / WaveLength;
    output.NormalMapPosition.y -= Time * WaveSpeed;

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float2 reflectionUV = postProjToScreen(input.ReflectionPosition) + halfPixel();

    float4 normal = tex2D(waterNormalSampler, input.NormalMapPosition) * 2 - 1;
    float2 UVOffset = WaveHeight * normal.rg;

    float3 reflection = tex2D(reflectionSampler, reflectionUV + UVOffset);

    return float4(lerp(reflection, BaseColor, BaseColorAmount), 1);
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_1_1 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}